package com.ipinyou.optimus.kernel.zk;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;

/**
 * ZooKeeper's custom znode data structure. Allows for easily information addition and retrieval.
 * 
 */
public class ZNRecord implements Serializable{

	private static final long serialVersionUID = -343873159838487133L;
	
	public static final String ERR_PARSED_RAW_DATA = "err_parsed_raw_data_crnsnl";
	
	String id;

    public String getId() {
        return id;
    }

    Map<String, String> simpleFields;
    Map<String, List<String>> listFields;
    Map<String, Map<String, String>> mapFields;

    private ZNRecord() {
    	
    }

    public ZNRecord(String id) {
        this.id = id;
        simpleFields = new TreeMap<String, String>();
        mapFields = new TreeMap<String, Map<String, String>>();
        listFields = new TreeMap<String, List<String>>();
    }

    public ZNRecord(ZNRecord that) {
        this(that.id);
        simpleFields.putAll(that.simpleFields);
        mapFields.putAll(that.mapFields);
        listFields.putAll(that.listFields);
    }

    public <K,V> String putAnyTypeSimpleField(K key,V value){
    	return simpleFields.put(String.valueOf(key), String.valueOf(value));
    }
    
    public String putSimpleField(String key, String value) {
        return simpleFields.put(key, value);
    }

    public String getSimpleField(String key) {
        return simpleFields.get(key);
    }
    
    public String getSimpleField(String key,String defaultValue) {
        String ret =  simpleFields.get(key);
        if(ret==null)ret = defaultValue;
        return ret;
    }

    public <K,V> List<String> putAnyTypeListField(K key, List<V> value) {
    	List<String> vals = new ArrayList<String>();
    	for (V val : value) {
			vals.add(String.valueOf(val));
		}
    	return listFields.put(String.valueOf(key), vals);
    }
    
    public List<String> putListField(String key, List<String> value) {
        return listFields.put(key, value);
    }

    public List<String> getListField(String key) {
        return listFields.get(key);
    }

    public Map<String, String> putMapField(String key, Map<String, String> value) {
        return mapFields.put(key, value);
    }

    public Map<String, String> getMapField(String key) {
        return mapFields.get(key);
    }

    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result + ((id == null) ? 0 : id.hashCode());
        result = prime * result + ((listFields == null) ? 0 : listFields.hashCode());
        result = prime * result + ((mapFields == null) ? 0 : mapFields.hashCode());
        result = prime * result + ((simpleFields == null) ? 0 : simpleFields.hashCode());
        return result;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == null) {
            return false;
        }
        if (obj instanceof ZNRecord) {
            ZNRecord that = (ZNRecord) obj;
            return this.id.equals(that.id) && this.simpleFields.equals(that.simpleFields)
                    && this.mapFields.equals(that.mapFields) && this.listFields.equals(that.listFields);
        }
        return false;
    }

	public Map<String, String> getSimpleFields() {
		return simpleFields;
	}

	public void setSimpleFields(Map<String, String> simpleFields) {
		this.simpleFields = simpleFields;
	}

	public Map<String, List<String>> getListFields() {
		return listFields;
	}

	public void setListFields(Map<String, List<String>> listFields) {
		this.listFields = listFields;
	}

	public Map<String, Map<String, String>> getMapFields() {
		return mapFields;
	}

	public void setMapFields(Map<String, Map<String, String>> mapFields) {
		this.mapFields = mapFields;
	}

	public void setId(String id) {
		this.id = id;
	}

	public <K,V> void putAnyTypeMapField(String key, Map<K, V> mapFields) {
		Map<String, String> value = new HashMap<String, String>();
		Set<K> keys = mapFields.keySet();
		for (K k : keys) {
			V v = mapFields.get(k);
			value.put(String.valueOf(k), String.valueOf(v));
		}
		putMapField(key, value);
	}
	
	@Override
	public String toString() {
		return "ZNRecord [id=" + id + ", simpleFields=" + simpleFields
				+ ", listFields=" + listFields + ", mapFields=" + mapFields
				+ "]";
	}

}
